package com.shuai.gateway.manager;


import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.stereotype.Component;

import java.util.Set;
import java.util.concurrent.TimeUnit;


@Component
@Slf4j
public class RandomManager {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 判断Redis中以该用户API-KEY为键值的list中是否存在随机数值val
     */
    public boolean existsVal(String key, long randomVal) {
        return redisTemplate.opsForList().indexOf(key, randomVal) != null;
    }


    /**
     * 向redis中对应key值下的list添加元素，开启了事务
     */
    public boolean putVal(String key, long randomVal) {
        Object succeed = redisTemplate.execute(new SessionCallback<Object>() {
            @Override
            public Object execute(RedisOperations operations) throws DataAccessException {
                redisTemplate.watch(key);
                // 检查key值是否存在
                Set<String> keys = redisTemplate.keys(key);
                if (keys != null && keys.size() > 0) {
                    redisTemplate.watch(keys);
                }

                boolean existsVal = existsVal(key, randomVal);
                if (existsVal) {
                    return false;
                }

                operations.multi(); // 开启redis事务
                try {
                    if (keys == null || keys.size() == 0) {
                        // 创建该key值对应的列表，并且指定过期时间为30min
                        redisTemplate.opsForList().leftPush(key, randomVal);
                        redisTemplate.expire(key, 60 * 30L, TimeUnit.SECONDS);
                    } else {
                        // 如果集合中不存在该随机数，则向其中添加
                        redisTemplate.opsForList().leftPush(key, randomVal);
                    }
                    operations.exec();  // 提交事务
                } catch (Exception e) {
                    log.error(e.getMessage());
                    operations.discard();   // 回滚事务
                    return Boolean.FALSE;
                }
                return Boolean.TRUE;
            }
        });
        return succeed != null && (Boolean) succeed;
    }
}